import { resources, SpriteFrame, TextAsset, Vec2 } from "cc";
/**
 * @class GameAssets
 * @description 游戏资源管理类，用于加载和获取游戏中的本地化资源。
 */
export default class GameAssets {
	private static lang_smap: Map<string, SpriteFrame> = new Map();
	private static coun_smap: Map<string, SpriteFrame> = new Map();
	private static lang_tmap: Map<string, string> = new Map();
	private static nickname: Array<string>;

	public static get Nickname(){
		return GameAssets.nickname;
	}

    /**
     * @method init
     * @param {string} country - 国家代码
     * @param {string} language - 语言代码
     * @description 初始化游戏资源，加载指定国家和语言的资源包。
     */
	public static async init(country: string, language: string){
		let [bundle_coun, bundle_lang] = await Promise.all(['coun-'+country, 'lang-'+language].map(bundle_name=>mtec.cc.loadBundle(bundle_name)));

		await (<const>[
			[GameAssets.coun_smap, bundle_coun],
			[GameAssets.lang_smap, bundle_lang]
		]).forWait(async ([smap, bundle])=>{
			await new Promise<SpriteFrame[]>((s, j)=>{
				bundle.loadDir('./', SpriteFrame, (err, assets)=>{
					if(err) j(err);
					else s(assets);
				});
			}).then(list=>{
				list.forEach(frame=>smap.set(frame.name, frame));
			});
		});

		await mtec.cc.loadResAsync('text', TextAsset, bundle_lang).then(file=>{
			let obj = mtec.parseJson(file.text.decodeAtoB);
			Reflect.ownKeys(obj).forEach(key=>GameAssets.lang_tmap.set(key as string, obj[key]));
		});

		await mtec.cc.loadResAsync('nickname', TextAsset, bundle_coun).then(file=> GameAssets.nickname = mtec.parseJson(file.text.decodeAtoB) );
	}

	/**
	 * 获取国家图标
	 * @param name
	 * @description 获取国家图标\
	 * 0: "btn-free-cache1"\
	 * 1: "btn-free-cache2"\
	 * 2: "btn-free-cache3"\
	 * 3: "btn-fruit-times"\
	 * 4: "icon-symbol-defeat"\
	 * 5: "icon-symbol-free"\
	 * 6: "icon-symbol"
	 */
	public static getCounTexture(name: string|number){
		if(typeof name == 'number') name = CounTextureName[name];
		if(!CounTextureName.includes(name)) name = CounTextureName[0];

		return GameAssets.coun_smap.get(name);
	}

	/**
	 * 获取语言本地化贴图
	 * @param name
	 * @description 获取语言本地化贴图\
	 * 0: "texture0"\
	 * 1: "texture1"\
	 * 2: "texture2"\
	 * 3: "texture3"\
	 * 4: "texture4"
	 */
	public static getLangTexture(name: string|number){
		if(typeof name == 'number') name = LangTextureName[name];
		if(!LangTextureName.includes(name)) throw new Error('Language texture not found');

		return GameAssets.lang_smap.get(name);
	}

	/**
	 * 获取语言本地化文本
	 * @param name
	 * @description 获取语言本地化文本\
	 * 0: "word0"\
	 * 1: "word1"\
	 * .\
	 * .\
	 * .\
	 * 89: "word89"
	 */
	public static getLangText(name: string|number, ...args: any[]){
		if(typeof name == 'number') name = LangTextName[name];
		if(!LangTextName.includes(name)) throw new Error('Language text not found');

		let str = GameAssets.lang_tmap.get(name).replace(/\\n/g, '\n');
		if(str && args.length > 0) args.forEach(($, i)=>str = str.replace(`{${i+1}}`, String($)));

		return str;
	}

	/** 随机获取一个用户昵称 */
	public static getNickname(){
		return mtec.array.random(GameAssets.nickname);
	}

	public static async loadRoundLayout(file_name: string){
		let round_layout: Array<{tier: number, element: Array<{id: number, coor: Array<{x: number, y: number}>}>}>;
		round_layout = await mtec.cc.loadResAsync('config/'+file_name, TextAsset, resources)
		.then(file=>mtec.parseJson(file.text.decodeAtoB));

		return round_layout
		.filter(el=>el.element.reduce((acc, cur)=>acc+cur.coor.length, 0) > 0)
		.sort((a, b)=>a.tier-b.tier)
		.map((el, i)=>{
			let coor = el.element.reduce((list, cur)=>{
				list.push(...cur.coor.map(e=>new Vec2(e.x, e.y+0.5)));// 纠正由淇的失误，布局统一调高半块砖
				return list;
			}, [] as Vec2[]);

			return {tier: i+1, coor};
		});
	}

	/**
	 * 加载关卡数据
	 * @param round 描述当前关卡的自然数, 从1开始
	 */
	public static async loadRoundData(round: number){
		let round_layout = await GameAssets.loadRoundLayout('level_'+round);
		let round_tile: { round: number; tiers: { tiers: number[]; tiles: { id: number; count: number; }[]; }[]; } = await mtec.cc.loadResAsync('config/round-tile', TextAsset, resources)
		.then(file=>mtec.parseJson(file.text.decodeAtoB).find(e=>(e.round+1)==round));

		let id_list = ['00', ...mtec.array.create(19, i=>(i+1).toString().padStart(2, '0')).sort(()=>Math.random()-0.5)];

		let temp: {tier: number, element: Map<string, Vec2[]>}[] = [];

		round_tile.tiers.forEach(conf=>{
			let bucket: [string, number][] = conf.tiles.map(({id, count})=>[id_list[id-1], count]);

			conf.tiers.forEach(tier=>{
				let item: typeof temp[number] = {tier, element: new Map()};
				temp.push(item);

				round_layout.find(el=>el.tier==tier).coor.forEach(c=>{
					let search = mtec.array.random(bucket);
					while(search[1] <= 0){
						mtec.array.remove(bucket, search);
						search = mtec.array.random(bucket);
					}
					search[1]--;
					if(!item.element.has(search[0])) item.element.set(search[0], []);
					item.element.get(search[0]).push(c);
				});
			});
		});

		return temp.map(({tier, element})=>{
			return {tier, element: Array.from(element).map(([id, coor])=>{
				return {id, coor};
			})};
		}).filter(el=>el.element.reduce((acc, cur)=>acc+cur.coor.length, 0) > 0)
		.sort((a, b)=>a.tier-b.tier)
		.map((el, i)=>{
			el.tier = i+1;
			return el;
		});
	}
}
//0: "btn-free-cache1"
//1: "btn-free-cache2"
//2: "btn-free-cache3"
//3: "btn-fruit-times"
//4: "icon-symbol-defeat"
//5: "icon-symbol-free"
//6: "icon-symbol"
const CounTextureName = [ "YnRuLWZyZWUtY2FjaGUx", "YnRuLWZyZWUtY2FjaGUy", "YnRuLWZyZWUtY2FjaGUz", "YnRuLWZydWl0LXRpbWVz", "aWNvbi1zeW1ib2wtZGVmZWF0", "aWNvbi1zeW1ib2wtZnJlZQ==", "aWNvbi1zeW1ib2w=" ].map(el=>el.decodeAtoB);

//0: "texture0"
//1: "texture1"
//2: "texture2"
//3: "texture3"
//4: "texture4"
const LangTextureName = [ "dGV4dHVyZTA=", "dGV4dHVyZTE=", "dGV4dHVyZTI=", "dGV4dHVyZTM=", "dGV4dHVyZTQ=" ].map(el=>el.decodeAtoB);

//0: "word0"
//1: "word1"
//...
//89: "word89"
const LangTextName = [ "d29yZDA=", "d29yZDE=", "d29yZDI=", "d29yZDM=", "d29yZDQ=", "d29yZDU=", "d29yZDY=", "d29yZDc=", "d29yZDg=", "d29yZDk=", "d29yZDEw", "d29yZDEx", "d29yZDEy", "d29yZDEz", "d29yZDE0", "d29yZDE1", "d29yZDE2", "d29yZDE3", "d29yZDE4", "d29yZDE5", "d29yZDIw", "d29yZDIx", "d29yZDIy", "d29yZDIz", "d29yZDI0", "d29yZDI1", "d29yZDI2", "d29yZDI3", "d29yZDI4", "d29yZDI5", "d29yZDMw", "d29yZDMx", "d29yZDMy", "d29yZDMz", "d29yZDM0", "d29yZDM1", "d29yZDM2", "d29yZDM3", "d29yZDM4", "d29yZDM5", "d29yZDQw", "d29yZDQx", "d29yZDQy", "d29yZDQz", "d29yZDQ0", "d29yZDQ1", "d29yZDQ2", "d29yZDQ3", "d29yZDQ4", "d29yZDQ5", "d29yZDUw", "d29yZDUx", "d29yZDUy", "d29yZDUz", "d29yZDU0", "d29yZDU1", "d29yZDU2", "d29yZDU3", "d29yZDU4", "d29yZDU5", "d29yZDYw", "d29yZDYx", "d29yZDYy", "d29yZDYz", "d29yZDY0", "d29yZDY1", "d29yZDY2", "d29yZDY3", "d29yZDY4", "d29yZDY5", "d29yZDcw", "d29yZDcx", "d29yZDcy", "d29yZDcz", "d29yZDc0", "d29yZDc1", "d29yZDc2", "d29yZDc3", "d29yZDc4", "d29yZDc5", "d29yZDgw", "d29yZDgx", "d29yZDgy", "d29yZDgz", "d29yZDg0", "d29yZDg1", "d29yZDg2", "d29yZDg3", "d29yZDg4", "d29yZDg5" ].map(el=>el.decodeAtoB);
